<?php

declare(strict_types=1);

namespace App\AdminApi\Modular\Data\Service;

use App\Common\Modular\Data\Serve\ResourceChunkServe;
use Core\Basics\BasicsModel;
use Zms\Unit\File;
use Core\Service\Uploader;
use Exception;
use League\Flysystem\FilesystemException;

/**
 * 广告服务层
 * Class BannerService
 */
class ResourcesChunkService extends ResourceChunkServe
{

    /**
     * 记录分片
     * @param string $key
     * @param string $path
     * @param int $index
     * @return bool|BasicsModel
     */
    public function record(string $key, string $path, int $index): bool|BasicsModel
    {
        return $this->created([
            'key' => $key, 'path' => $path, 'index' => $index
        ]);
    }


    /**
     * 合并分片文件,仅限本地上传
     * @param string $key
     * @param int $total
     * @return ?array
     */
    public function mergeChunkFiles(string $key, int $total): ?array
    {
        try {
            $chunk = $this->search(['key' => $key])->orderByRaw('`index` ASC')->get()->toArray();
            if (count($chunk) !== $total) {
                return null;
            }
            $uploader = container(Uploader::class);
            $filesystem = $uploader->drive('local');
            $path = '';
            foreach ($chunk as $index => $row) {
                if (!$filesystem->has($row['path'])) return null;
                if ($index === 0) {
                    $path = $row['path'];
                } else {
                    $status = File::appendWrite($uploader->getLocalFilePath($path), $filesystem->read($row['path']));
                    if ($status === null) {
                        return null;
                    }
                }
            }
            $newsName = File::changeFileName($path);
            if (rename($uploader->getLocalFilePath($path), $uploader->getLocalFilePath($newsName))) {
                return ['path' => $newsName, 'url' => $uploader->domain() . '/' . trim($newsName, '/')];
            }
            return null;
        } catch (FilesystemException|Exception) {
            return null;
        }
    }
}